import os
import sys
import datetime

from PyQt5.QtWidgets import *
from PyQt5.QtSql import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *


def field_column(model):

    """ Создание словаря для QSqlQueryModel.
    Ключ - имя поля, значение - номер столбца."""
    D = {}
    for i in range(model.columnCount()):
        D[model.record().fieldName(i)] = i
    return D

    
class ModuleDesigner(QDialog):
    """
    """
    def __init__(self, parent, rec_id):
        super().__init__(parent)
        
        self.rec_id = rec_id
        self.pict_empty = QPixmap('pict\\emptytrash.png')
        self.pict_full = QPixmap('pict\\fulltrash.png')
        self.initUI()
        self.load_data(rec_id)
    
    def initUI(self):

        #self.setStyleSheet("QLineEdit { background-color: yellow },"
        #                   "QGroupBox { background-color: red }")
        # self.edt_num_asu_new.setStyleSheet("background-color : red")

        """ ЛЕВАЯ МАТРЕШКА."""

        """ЗАДАНИЕ"""
        self.cmb_class = QComboBox()
        self.form_class = QFormLayout()
        self.form_class.addRow("ЗАДАНИЕ", self.cmb_class)

        """ ИЗМЕНИТЬ и СТАРЫЙ МАКЕТ """
        self.cmb_modification = QComboBox()
        self.edt_num_asu_old = QLineEdit()
        """на форму"""
        self.form_old_hide = QFormLayout()
        self.form_old_hide.addRow("ИЗМЕНИТЬ", self.cmb_modification)
        self.form_old_hide.addRow("СТАРЫЙ МАКЕТ", self.edt_num_asu_old)
        """в рамку (скрыта по умолчанию)"""
        self.box_old_hide = QGroupBox()
        self.box_old_hide.setLayout(self.form_old_hide)
        self.box_old_hide.hide()


        lbl_note = QLabel("КОММЕНТАРИЙ")
        self.pte_note = QPlainTextEdit()

        self.chb_quickly = QCheckBox("СРОЧНО")
        btn_start = QPushButton('НАЧАТЬ ВЫПОЛНЕНИЕ')
        # btn_quit.clicked.connect(self.set_order)
        btn_finish = QPushButton('ЗАКАЗ ГОТОВ')
        # btn_quit.clicked.connect(self.set_order)
        """в контейнер"""
        vbox_L = QVBoxLayout()
        vbox_L.addLayout(self.form_class)                                       # ЗАДАНИЕ
        vbox_L.addWidget(self.box_old_hide)                                     # ИЗМЕНИТЬ и СТАРЫЙ МАКЕТ
        vbox_L.addWidget(lbl_note)                                              #
        vbox_L.addWidget(self.pte_note)                                         #
        vbox_L.addWidget(self.chb_quickly)                                      # СРОЧНО
        vbox_L.addWidget(btn_start)                                              # КНОПКА
        vbox_L.addWidget(btn_finish)                                              # КНОПКА

        """ В рамку."""
        box_control = QGroupBox("ЭЛЕМЕНТЫ УПРАВЛЕНИЯ")
        box_control.setStyleSheet(
            "QGroupBox::title {subcontrol-position: top center;}")
        box_control.setLayout(vbox_L)

        """ ПРАВАЯ ПОЛОВИНА ФОРМЫ--------------------------------------------"""

        """ОБЯЗАТЕЛЬНЫЕ ПАРАМЕТРЫ.-------------------------------------------"""

        self.cmb_city = QComboBox()
        self.edt_num_asu_new = QLineEdit()
        self.edt_place = QLineEdit()
        self.edt_num_out = QLineEdit()
        self.edt_proportions = QLineEdit()
        """ Эти элементы должны быть скрыты в макете заказчика, поэтому заключаем
        их в отдельный QGroupBox."""
        self.form_hide_maket = QFormLayout()
        self.form_hide_maket.addRow("№ АСУ", self.edt_num_asu_new)
        self.form_hide_maket.addRow("РУБРИКА", self.edt_place)
        self.form_hide_maket.addRow("НОМЕР ВЫХОДА", self.edt_num_out)
        self.box_hide_maket = QGroupBox()
        self.box_hide_maket.setLayout(self.form_hide_maket)
        """ Складываем на форму."""
        self.form_main = QFormLayout()
        self.form_main.addRow("ГАЗЕТА ВЫХОДА", self.cmb_city)
        self.form_main.addRow(self.box_hide_maket)
        self.form_main.addRow("ФОРМАТ МОДУЛЯ", self.edt_proportions)
        """ В рамку."""
        box_main = QGroupBox("ОБЯЗАТЕЛЬНЫЕ ПАРАМЕТРЫ")
        box_main.setLayout(self.form_main)

        """ ДОПОЛНИТЕЛЬНЫЕ ПАРАМЕТРЫ.----------------------------------------"""

        """ цвет, картинка, форма."""
        self.edt_color = QLineEdit()
        self.edt_picture = QLineEdit()
        self.edt_form = QLineEdit()
        """ Располагаем на форме."""
        form_add_hide = QFormLayout()
        form_add_hide.addRow("ЦВЕТ", self.edt_color)
        form_add_hide.addRow("КАРТИНКА", self.edt_picture)
        form_add_hide.addRow("ФОРМА", self.edt_form)
        """ Заключаем в рамку (виджет для скрытия) ."""
        self.box_add = QGroupBox("ДОПОЛНИТЕЛЬНЫЕ ПАРАМЕТРЫ")
        self.box_add.setStyleSheet(
            "QGroupBox::title {subcontrol-position: top center;}")
        self.box_add.setLayout(form_add_hide)

        """ КОРЗИНА ДЛЯ ДОКУМЕНТОВ"""
        lbl_docum = QLabel("КОРЗИНА ДЛЯ ДОКУМЕНТОВ")                            # КОРЗИНА ДЛЯ ФАЙЛОВ#
        self.lbl_docum_box = DocumBox(self)                                     # сама корзина
        self.lbl_docum_box.setContextMenuPolicy(Qt.CustomContextMenu)           # разрешаем контекстное меню
        self.lbl_docum_box.customContextMenuRequested.connect(self.sc_menu_docum)# соединяем с меню
        self.edt_docum = QLineEdit()                                            # поле названия файла
        self.edt_docum.setReadOnly(True)                                        # название файла только для чтения
        vbox_docum = QVBoxLayout()                                              # в контейнер складываем:
        vbox_docum.addWidget(lbl_docum, alignment=Qt.AlignCenter)               # КОРЗИНА ДЛЯ ФАЙЛОВ
        vbox_docum.addWidget(self.lbl_docum_box, alignment=Qt.AlignCenter)      # сама корзина
        vbox_docum.addWidget(self.edt_docum,)                                   # поле названия файла

        """  Вертикальный првый. Основные и дополнительные виджеты."""
        vbox_r = QVBoxLayout()
        vbox_r.addWidget(box_main)
        vbox_r.addWidget(self.box_add)
        vbox_r.addLayout(vbox_docum)

        """ Горизонтальный контейнер."""
        hbox = QHBoxLayout()
        hbox.addWidget(box_control)
        hbox.addLayout(vbox_r)

        self.setLayout(hbox)
        self.setWindowModality(1)
        self.setWindowTitle("МОДУЛЬ")
        self.resize(500,50)
        self.show()
        lineEdits = self.findChildren(QLineEdit)
        for widget in lineEdits:
            widget.setReadOnly(True)
        print(lineEdits)


    def load_data(self, rec_id):

        """ ЗАДАНИЕ."""
        items = ("ЧТО ДЕЛАТЬ?", "НОВЫЙ","ИЗМЕНЕНИЯ",">-------------<","МАКЕТ ЗАКАЗЧИКА")
        self.model_class = QStringListModel(items, self)
        self.cmb_class.setModel(self.model_class)

        """ ЗАДАНИЕ."""
        items = ("ЧТО НЕОБХОДИМО ИЗМЕНИТЬ?", "ТЕКСТ","ДИЗАЙН","ФОРМАТ")
        self.model_modification = QStringListModel(items, self)
        self.cmb_modification.setModel(self.model_modification)

        """ ГАЗЕТА."""
        items = ("ДЛЯ КАКОГО ГОРОДА?", "САМАРА","ТОЛЬЯТТИ")
        self.model_city = QStringListModel(items, self)
        self.cmb_city.setModel(self.model_city)

        """ Модель для заполнения остальных полей. Берём одну запись."""
        self.model = QSqlQueryModel()
        sql = ("SELECT class, modification, num_asu_old, city, "
            "num_asu_new, place, num_out, proportions, color, "
            "picture, form, note, logo_name, quickly, rec_id "
            "FROM store "
            "WHERE rec_id={};".format(rec_id))
        self.model.setQuery(sql)
        if self.model.lastError().isValid ():
            logging.critical('TabModel: {}'.format( self.model.lastError().text()))
            quit()
        """ Подключаем """
        column = field_column(self.model)
        self.mapper = QDataWidgetMapper(self)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.setModel(self.model)
        self.mapper.addMapping(self.cmb_class, column['class'], 'currentIndex')
        self.mapper.addMapping(self.cmb_modification, column['modification'], 'currentIndex')
        self.mapper.addMapping(self.edt_num_asu_old, column['num_asu_old'])
        self.mapper.addMapping(self.cmb_city, column['city'], 'currentIndex')
        self.mapper.addMapping(self.edt_num_asu_new, column['num_asu_new'])
        self.mapper.addMapping(self.edt_place, column['place'])
        self.mapper.addMapping(self.edt_num_out, column['num_out'])
        self.mapper.addMapping(self.edt_proportions, column['proportions'])
        self.mapper.addMapping(self.edt_color, column['color'])
        self.mapper.addMapping(self.edt_picture, column['picture'])
        self.mapper.addMapping(self.edt_form, column['form'])
        self.mapper.addMapping(self.pte_note, column['note'])
        self.mapper.addMapping(self.edt_docum, column['logo_name'])
        self.mapper.addMapping(self.chb_quickly, column['quickly'])

        self.mapper.toFirst()

        if self.edt_docum.text():
            self.lbl_docum_box.setPixmap(self.pict_full)


    def class_changed(self,index):
        if index == 1:
            self.box_old_hide.hide()
            self.box_hide_maket.show()
            self.box_add.show()

        if index == 2:
            self.box_old_hide.show()
            self.box_hide_maket.show()
            self.box_add.show()

        if index == 4:
            self.box_old_hide.hide()
            self.box_hide_maket.hide()
            self.box_add.hide()


    def set_order(self):

        """ПРОВЕРКА ЗАПОЛНЕНИЯ ПОЛЕЙ"""
        if self.cmb_class.currentIndex() not in (1,2,4):
            QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                "В поле ЗАДАНИЕ нужно выбрать: <НОВЫЙ>, <ИЗМЕНЕНИЯ> или <МАКЕТ ЗАКАЗЧИКА>.")
            return
        if (self.cmb_class.currentIndex()==2):
            if self.cmb_modification.currentIndex()==0:
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "В поле ИЗМЕНИТЬ нужно выбрать:  <ТЕКСТ>, <ДИЗАЙН> или <ФОРМАТ>.")
                return
            if self.edt_num_asu_old.text()=='':
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "В поле СТАРЫЙ МАКЕТ нужно указать номер старого модуля из АСУ газеты.")
                return
        if self.cmb_city.currentIndex()==0:
            QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                "В поле ГАЗЕТА нужно выбрать: <ТОЛЬЯТТИ> или <САМАРА>.")
            return
        if self.cmb_class.currentIndex() in (1,2):
            if self.edt_num_asu_new.text()=='':
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "В поле № АСУ нужно указать номер нового модуля из АСУ газеты.")
                return
            if self.edt_place.text()=='':
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "В поле РУБРИКА нужно указать рубрику нового модуля из АСУ газеты.")
                return
            if self.edt_num_out.text()=='':
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "В поле НОМЕР ВЫХОДА нужно указать номер газеты.")
                return
        if self.edt_proportions.text()=='':
            QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                "В поле ФОРМАТ МОДУЛЯ нужно указать формат модуля.")
            return
        if self.cmb_class.currentIndex()==4:
            if self.edt_docum.text()=='':
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "Положите макет заказчика В КОРЗИНУ ДЛЯ ДОКУМЕНТОВ.")
                return

        """ Поставить в очередь. Сохранить результаты"""
        self.model.setData(self.model.index(0,DATA_READY), 1)
        d = datetime.datetime.today()
        self.model.setData(self.model.index(0,DATE_ORDER), d.strftime('%Y-%m-%d %H:%M:%S'))
        self.mapper.submit()
        self.accept()

    def closeEvent(self,е):
        """ Закрытие формы крестиком."""
        self.accept()

        
        
        
        
        
        
        
        
        
        
        
        

    """ КОНТЕКСТНОЕ МЕНЮ / КОЗИНА ДЛЯ ДОКУМЕНТОВ.----------------------------"""
    def sc_menu_docum(self, pos):

        menu = QMenu(self)
        menu.addAction("Добавить документ", self.add_file)
        menu.addAction("Очистить корзину", self.delete_file)
        menu.exec_(QCursor.pos())

    def add_file(self):
        """ ДОБАВИТЬ ДОКУМЕНТ в КОРЗИНУ.
        Находим путь до рабочего стола. Открываем диалог открытия файла."""
        user_profile = os.environ['USERPROFILE']
        user_desktop = user_profile + "/Desktop"
        url, filter  = QFileDialog.getOpenFileName(self,
            caption="Заголовок окна", directory=user_desktop,
            filter="All(*.*)")
        """ записываем file_name во внутреннюю переменную."""
        if url:
            print(url)
        file_to_blob(url, self.rec_id)
        path, file = os.path.split(url)
        self.edt_docum.setText(file)
        self.lbl_docum_box.setPixmap(self.pict_full)


    def delete_file(self):
        """ Очистить корзину."""
        print('Очистить корзину.')
        query = QSqlQuery()
        query.exec("UPDATE store SET logo=NULL WHERE rec_id = {};"
            .format(self.rec_id))
        self.edt_docum.setText("")
        self.lbl_docum_box.setPixmap(self.pict_empty)


class DocumBox(QLabel):
    """ ВИДЖЕТ - КОРЗИНА ДЛЯ ДОКУМЕНТОВ"""

    def __init__(self, dialog):
        super().__init__()

        """ Запомнить ссылку на диалог, чтобы иметь доступ ко всем виджетам
        формы. Разрешаем прием. Нужны две картинки: пустая корзин, полная
        корзина."""
        self.dialog = dialog
        self.setAcceptDrops(True)
        self.setPixmap(dialog.pict_empty)

    def dragEnterEvent(self, event):

        """ Если сбрасывается URL файлов, то разрешаем."""
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):

        """ Можно сбросить только один файл. """
        urls = []
        for url in event.mimeData().urls():
            urls.append(url.toLocalFile())
        if len(urls) > 1:
            QMessageBox.critical(self,"НЕВОЗМОЖНО СОХРАНИТЬ",
                "Можно сохранить только один файд любого типа.")
        """ Сохраняем файл в БД. Сохраняем название файла. Меняем картинку на
        полную корзину."""
        url = urls[0]
        file_to_blob(url, self.dialog.rec_id)
        path, file = os.path.split(url)
        self.dialog.edt_docum.setText(file)
        self.setPixmap(self.dialog.pict_full)


def file_to_blob(url, rec_id):

    data = open(url, 'rb').read()
    query = QSqlQuery()
    query.prepare("UPDATE store SET logo=(:data) WHERE rec_id = {};"
        .format(rec_id))
    query.bindValue(":data", QByteArray(data))
    query.exec_()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    app.setStyleSheet(
            """QGroupBox {
            border: 1px solid gray;
            border-radius: 3px;
            margin: 10px;
            padding: 4px;
            }

            QGroupBox::title {
            subcontrol-origin: margin;
            subcontrol-position: top center;
            padding: 4px;
            }"""    )

    os.chdir('..')                                                              # уходим в рабочий каталог головного модуля куда потом он будет импортирован

    import logging
    logging.basicConfig(filename='modulemenager.log',level=logging.DEBUG,
        format = u'%(filename)s[LINE:%(lineno)d]# %(levelname)-8s %(message)s')

    from connmysql import get_db_mysql
    db = get_db_mysql("order.ini")
    if not db:
        logging.error('Нет соединения с БД')
        print("нет соединения")
        quit()

    module = ModuleDesigner(None,'1388')
    module.exec_()
    db.close()
    quit()

    sys.exit(app.exec_())
